package com.purchasing.system.controller;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.HashSet;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;

import com.purchasing.system.model.User;
import com.purchasing.system.model.Role;
import com.purchasing.system.model.Permission;
import com.purchasing.system.model.ERole;
import com.purchasing.system.payload.request.ChangePasswordRequest;
import com.purchasing.system.payload.request.UpdateProfileRequest;
import com.purchasing.system.payload.request.CreateUserRequest;
import com.purchasing.system.payload.request.UpdateUserRequest;
import com.purchasing.system.payload.response.JwtResponse;
import com.purchasing.system.payload.response.MessageResponse;
import com.purchasing.system.repository.UserRepository;
import com.purchasing.system.repository.RoleRepository;
import com.purchasing.system.security.services.UserDetailsImpl;

import javax.validation.Valid;

@CrossOrigin(origins = "*", maxAge = 3600)
@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    UserRepository userRepository;
    
    @Autowired
    RoleRepository roleRepository;
    
    @Autowired
    PasswordEncoder encoder;
    
    @GetMapping("/info")
//    @PreAuthorize("hasRole('EMPLOYEE') or hasRole('ADMIN')")
    public ResponseEntity<?> getUserInfo() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal();
        
        List<String> roles = userDetails.getAuthorities().stream()
                .map(item -> item.getAuthority())
                .collect(Collectors.toList());
        
        return ResponseEntity.ok(new JwtResponse(
                null,
                userDetails.getId(),
                userDetails.getUsername(),
                userDetails.getEmail(),
                userDetails.getName(),
                userDetails.getDepartment(),
                roles));
    }
    
    @GetMapping("/list")
//    @PreAuthorize("hasRole('SUPER_ADMIN')")
    public ResponseEntity<Page<User>> getAllUsers(
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size,
            @RequestParam(required = false, defaultValue = "") String username,
            @RequestParam(required = false, defaultValue = "") String name,
            @RequestParam(required = false, defaultValue = "") String department) {
        
        Pageable pageable = PageRequest.of(page, size);
        Page<User> users = userRepository.findByUsernameContainingAndNameContainingAndDepartmentContaining(
                username, name, department, pageable);
        
        return ResponseEntity.ok(users);
    }
    
    @PostMapping("/create")
//    @PreAuthorize("hasRole('SUPER_ADMIN')")
    public ResponseEntity<?> createUser(@Valid @RequestBody CreateUserRequest createRequest) {
        if (userRepository.existsByUsername(createRequest.getUsername())) {
            return ResponseEntity.badRequest().body(new MessageResponse("Error: Username is already taken!"));
        }
        
        if (userRepository.existsByEmail(createRequest.getEmail())) {
            return ResponseEntity.badRequest().body(new MessageResponse("Error: Email is already in use!"));
        }
        
        // 创建新用户
        User newUser = new User();
        newUser.setUsername(createRequest.getUsername());
        newUser.setEmail(createRequest.getEmail());
        newUser.setPassword(encoder.encode(createRequest.getPassword()));
        newUser.setName(createRequest.getName());
        newUser.setPhone(createRequest.getPhone());
        newUser.setDepartment(createRequest.getDepartment());
        
        Set<Role> roles = new HashSet<>();
        if (createRequest.getRoles() != null && !createRequest.getRoles().isEmpty()) {
            createRequest.getRoles().forEach(roleName -> {
                // 移除 "ROLE_" 前缀（如果存在）
                String roleNameStr = roleName.startsWith("ROLE_") ? roleName : "ROLE_" + roleName.toUpperCase();
                Role role = roleRepository.findByName(ERole.valueOf(roleNameStr))
                        .orElseThrow(() -> new RuntimeException("Error: Role " + roleName + " is not found."));
                roles.add(role);
            });
        } else {
            // 如果没有指定角色，默认设置为普通员工
            Role userRole = roleRepository.findByName(ERole.ROLE_EMPLOYEE)
                    .orElseThrow(() -> new RuntimeException("Error: Role is not found."));
            roles.add(userRole);
        }
        newUser.setRoles(roles);
        
        userRepository.save(newUser);
        
        return ResponseEntity.ok(new MessageResponse("User created successfully!"));
    }
    
    @PutMapping("/{id}")
//    @PreAuthorize("hasRole('SUPER_ADMIN')")
    public ResponseEntity<?> updateUser(@PathVariable Long id, @Valid @RequestBody UpdateUserRequest userDetails) {
        User user = userRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("Error: User not found."));
        
        // 检查用户名是否重复（如果更改了用户名）
        if (!user.getUsername().equals(userDetails.getUsername()) && 
            userRepository.existsByUsername(userDetails.getUsername())) {
            return ResponseEntity.badRequest().body(new MessageResponse("Error: Username is already taken!"));
        }
        
        // 检查邮箱是否重复（如果更改了邮箱）
        if (!user.getEmail().equals(userDetails.getEmail()) && 
            userRepository.existsByEmail(userDetails.getEmail())) {
            return ResponseEntity.badRequest().body(new MessageResponse("Error: Email is already in use!"));
        }
        
        // 更新用户信息，但保留原密码
        user.setUsername(userDetails.getUsername());
        user.setEmail(userDetails.getEmail());
        user.setName(userDetails.getName());
        user.setPhone(userDetails.getPhone());
        user.setDepartment(userDetails.getDepartment());
        
        userRepository.save(user);
        
        return ResponseEntity.ok(new MessageResponse("User updated successfully!"));
    }
    
    @PutMapping("/{id}/roles")
//    @PreAuthorize("hasRole('SUPER_ADMIN')")
    public ResponseEntity<?> updateUserRoles(@PathVariable Long id, @RequestBody List<String> roles) {
        // 验证输入
        if (roles == null || roles.isEmpty()) {
            return ResponseEntity.badRequest()
                .body(new MessageResponse("Error: Roles list cannot be empty"));
        }

        User user = userRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("Error: User not found."));
        
        Set<Role> newRoles = new HashSet<>();
        for (String roleName : roles) {
            // 验证角色名不为空
            if (roleName == null || roleName.trim().isEmpty()) {
                return ResponseEntity.badRequest()
                    .body(new MessageResponse("Error: Role name cannot be empty"));
            }

            try {
                // 移除 "ROLE_" 前缀（如果存在）并转换为大写
                String normalizedRoleName = roleName.startsWith("ROLE_") ? 
                    roleName.toUpperCase() : "ROLE_" + roleName.toUpperCase();
                
                ERole roleEnum = ERole.valueOf(normalizedRoleName);
                Role role = roleRepository.findByName(roleEnum)
                    .orElseThrow(() -> new RuntimeException("Error: Role " + roleName + " is not found."));
                newRoles.add(role);
            } catch (IllegalArgumentException e) {
                return ResponseEntity.badRequest()
                    .body(new MessageResponse("Error: Invalid role name: " + roleName));
            }
        }
        
        user.setRoles(newRoles);
        userRepository.save(user);
        
        return ResponseEntity.ok(new MessageResponse("User roles updated successfully!"));
    }
    
    @DeleteMapping("/{id}")
//    @PreAuthorize("hasRole('SUPER_ADMIN')")
    public ResponseEntity<?> deleteUser(@PathVariable Long id) {
        User user = userRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("Error: User not found."));
        
        // 不允许删除超级管理员
        if (user.getRoles().stream().anyMatch(role -> role.getName() == ERole.ROLE_SUPER_ADMIN)) {
            return ResponseEntity.badRequest().body(new MessageResponse("Error: Cannot delete super admin user!"));
        }
        
        userRepository.delete(user);
        return ResponseEntity.ok(new MessageResponse("User deleted successfully!"));
    }
    
    @PutMapping("/profile")
//    @PreAuthorize("hasRole('EMPLOYEE') or hasRole('ADMIN')")
    public ResponseEntity<?> updateProfile(@Valid @RequestBody UpdateProfileRequest updateRequest) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal();
        
        User user = userRepository.findById(userDetails.getId())
                .orElseThrow(() -> new RuntimeException("Error: User not found."));
        
        user.setName(updateRequest.getName());
        user.setDepartment(updateRequest.getDepartment());
        user.setPhone(updateRequest.getPhone());
        
        userRepository.save(user);
        
        return ResponseEntity.ok(new MessageResponse("Profile updated successfully!"));
    }
    
    @PutMapping("/change-password")
//    @PreAuthorize("hasRole('EMPLOYEE') or hasRole('ADMIN')")
    public ResponseEntity<?> changePassword(@Valid @RequestBody ChangePasswordRequest passwordRequest) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal();
        
        User user = userRepository.findById(userDetails.getId())
                .orElseThrow(() -> new RuntimeException("Error: User not found."));
        
        if (!encoder.matches(passwordRequest.getOldPassword(), user.getPassword())) {
            return ResponseEntity.badRequest().body(new MessageResponse("Error: Old password is incorrect!"));
        }
        
        user.setPassword(encoder.encode(passwordRequest.getNewPassword()));
        userRepository.save(user);
        
        return ResponseEntity.ok(new MessageResponse("Password changed successfully!"));
    }


    // 获取用户所有权限
    @GetMapping("/{userId}/permissions")
//    @PreAuthorize("hasRole('SUPER_ADMIN')")
    public ResponseEntity<Set<String>> getUserPermissions(@PathVariable Long userId) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new RuntimeException("Error: User not found."));

        Set<String> permissions = user.getRoles().stream()
                .flatMap(role -> role.getPermissions().stream())
                .map(Permission::getName)
                .collect(Collectors.toSet());

        return ResponseEntity.ok(permissions);
    }

    // 检查用户是否有特定权限
    @GetMapping("/{userId}/has-permission")
//    @PreAuthorize("hasRole('SUPER_ADMIN')")
    public ResponseEntity<Boolean> checkUserPermission(
            @PathVariable Long userId,
            @RequestParam String permission) {

        User user = userRepository.findById(userId)
                .orElseThrow(() -> new RuntimeException("Error: User not found."));

        boolean hasPermission = user.getRoles().stream()
                .flatMap(role -> role.getPermissions().stream())
                .anyMatch(p -> p.getName().equals(permission));

        return ResponseEntity.ok(hasPermission);
    }
} 